package org.NooLab.astor;



import java.util.Map;
 


import org.NooLab.utilities.files.DFutils;
import org.NooLab.utilities.files.PathFinder;
import org.NooLab.utilities.logging.LogControl;
import org.NooLab.utilities.logging.PrintLog;
import org.NooLab.utilities.resources.ResourceLoader;
 
import org.NooLab.astor.app.up.IniProperties;
import org.NooLab.astor.app.up.AstorSomStartup;


import org.NooLab.field.FieldIntf;
 
 
import org.NooLab.itexx.storage.DataStreamProviderIntf;
import org.NooLab.itexx.storage.TexxDataBaseSettingsIntf;
import org.NooLab.itexx.storage.somfluid.db.DataBaseAccessDefinition;
import org.NooLab.somfluid.SomFluidFactory;
import org.NooLab.somfluid.SomFluidProperties;
import org.NooLab.somfluid.SomFluidPropertiesHandler;
import org.NooLab.somfluid.SomFluidPropertiesHandlerIntf;

import org.NooLab.somfluid.app.up.SomFluidStartup;
import org.NooLab.somfluid.applet.SomApplet;

import org.NooLab.somfluid.properties.PersistenceSettings;
import org.NooLab.somfluid.storage.ContainerStorageDevice;
import org.NooLab.somfluid.storage.FileOrganizer;
import org.NooLab.somfluid.structures.VariableSettingsHandlerIntf;
 
import org.NooLab.somfluid.tasks.SomFluidMonoTaskIntf;
import org.NooLab.somfluid.tasks.SomFluidProbTaskIntf;
 
import org.NooLab.structures.AppInstanceAbstract;

import org.NooLab.structures.ArgumentsCliReaderAbstract;
import org.NooLab.structures.ArgumentsIntf;
import org.NooLab.structures.ITexxPublicIntf;
import org.NooLab.structures.InstanceProcessControlIntf;
import org.NooLab.structures.SomTaskDependProcessIntf;
import org.NooLab.structures.ArgumentsPublicIntf;


/*
 * TRECHNICAL REMARK !!!!
 * 
 * when running AstorSomApp directly, the projects should be included directly as output;
 * when running it through iTexx, the jars should be included instead into the classpath...
 * 
 *  
 * 
 * 
 */


/**
 * 
 * if running in iTexx, iTexx is controlling whether to start the Astor from scratch
 * or whether to resume = loading a previously created Astor SOM (default).
 * iTexx always assumes resume=true
 * 
 * If there is no flag or no astor base model it starts from the scratch, else
 * it reloads the existing one
 * 
 * Astor-SOMs (as well as others) write an entry into a small xml status file
 * whether they COULD be started as a resume  
 * 
 * 
 *
 * Technical remark:
 * it is very important to start the JVM with the following parameters !!
 * 
   -Xmx1140m
   -XX:+ExplicitGCInvokesConcurrent
   -XX:+UseConcMarkSweepGC

 */
public class AstorSomApp {


	
	//=========================================================================
	public static void main(String[] args) {

		try {
			
			new AstorSomApp(args);
				
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		


	}
	//=========================================================================

	
	public AstorSomApp(String[] args){
		
		try {
			
			AstorSomStartup.setApplicationID("astorapp", this.getClass());

			(new App( 0, (new Arguments()).parse(args), this.getClass())).go();
		
		} catch (Exception e) {
			e.printStackTrace();
		}
		 
	}

	
}
// ----------------------------------------------------------------------------



@SuppressWarnings("rawtypes")
class App{
	
	public String processName;
	public String secret;

	SomApplet iapplet ;
	AstorInstance astorInstance;
	 
	ArgumentsPublicIntf arguments;
	
	PrintLog out ;
	DFutils fileutil = new DFutils();
	boolean instanceStopped;

	// ========================================================================
	
	public App( int as_service, ArgumentsPublicIntf args, Class pubClass) {	
	
		String fname = "" ; 
		
		arguments = args;
		
		// use LogControl to control output of log messages
		LogControl.globeScope = 2; // 1=local definitions  default = 2
		LogControl.Level = 2 ;     // the larger the more detailed logging... (could be really verbose!)

		out = new PrintLog(2, true) ;
		out.setPrefix("[AstorSomApp]") ;
		
		boolean rB = checkForAppletMode();
		
		if (rB){
			return;
		}

		
		try {
			String lastCfgFile ="" ;
			
			AstorSomStartup.setProjectSpaceLabel( arguments.getProjectName()) ;
			AstorSomStartup.setLastProjectName(arguments.getProjectName());
			
			IniProperties.loadIniFile() ;
			
			lastCfgFile = AstorSomStartup.getLastDataSet();
			if ((lastCfgFile==null) || (lastCfgFile.trim().length()<=1)){
				if (AstorSomStartup.getApplicationID().length()==0 ){
					AstorSomStartup.setApplicationID( this.getClass().getName().toLowerCase(),pubClass ) ;
				}
				
			}
			IniProperties.saveIniProperties() ;
			
			if (DFutils.fileExists(arguments.getConfigFile())==false){
				if ((arguments.getConfigFile().length()>0)){

					
					// lastCfgFile = IniProperties.dataSource ;
					if (arguments.getProjectName().length()==0){
						arguments.setProjectName ( "default") ;
					}
					
					fname = DFutils.createPath( arguments.getHomeDir(), arguments.getProjectName()+"/config/") ;
					fname = DFutils.createPath( fname, arguments.getConfigFile()) ;
					if (DFutils.fileExists(fname)){
						arguments.setConfigFile (fname);
					}else{
						if (fileutil.filenameIsUsable(fname)){
							arguments.setConfigFile (fname);
						}
					}
				}
				
				
				
				if (DFutils.fileExists(arguments.getConfigFile())==false){

					// this takes the internal resources and creates an external file from it
					
					createDefaultConfig();

					// we need not to stop in the iTexx context
					if (arguments.getContextMode().contentEquals(InstanceProcessControlIntf._APP_CONTEXT_ITEXX)==false){
						String msgstr = "you now have to edit the configuration file : \n" +
						                 "  " + arguments.getConfigFile();
						AstorSomStartup.showMsg(msgstr);

						// DocoServStartup.introduceDataSet(
						// arguments.configFile ) ;

						IniProperties.saveIniProperties();
						// copy the filename to the system clipboard
						System.exit(0);
					}

				}else{
					
				}
				
			}
			
			IniProperties.saveIniProperties() ;
			
			_showCurrentInputSettings();
			
			
			fname=fname+" " ;
			
		} catch (Exception e) {
			e.printStackTrace();
		}

		
		
	}
	

	private boolean checkForAppletMode() {

		boolean rB=false;
		
		if (arguments.startApplet() ){
		
			// start applet, stop this 
			// PApplet.main( new String[] { "org.NooLab.docserver.DocumentObserverApplet","a","b" });
			// PApplet applet = new PApplet();

			// see http://wiki.processing.org/w/Setting_width/height_dynamically
			iapplet = new SomApplet();
			
			iapplet.getInstance() ;
			
			while (iapplet!=null){
				PrintLog.Delay(100);
			}
			rB=true;
		}
		return rB ;
	}

	private void createDefaultConfig() throws Exception {
		 
		String filename = "", filstr,resourcePath;
		boolean rB;

		resourcePath = "org/NooLab/somfluid/app/astor/resources/somfluid-config-xml" ;
		ResourceLoader rsrcLoader = new ResourceLoader();   
		
		rB = rsrcLoader.loadTextResource( this.getClass(), resourcePath  ) ;
		if (rB){  
			filstr = rsrcLoader.getTextResource();
			
			filename = arguments.getConfigFile() ;
			
			fileutil.manageBakFile(filename, 10);
			fileutil.writeFileSimple( filename , filstr);
			
		}else{
			throw(new Exception("unable to load resources (create-db-sql-xml) or \n"+
					            "to create a new configuration file : "+filename)) ;
		}


		
	}


	
	private void _showCurrentInputSettings(){
		String  pathitx="";
		
		if (arguments.getContextMode().contentEquals(InstanceProcessControlIntf._APP_CONTEXT_ITEXX) ){
			pathitx = "app/Astor";
		}else{

			if (AstorSomStartup.isConfigAvailable(pathitx) == false) {

			}
		}
		out.print(1,"current project : "+ AstorSomStartup.getLastProjectName());
		 
	}


	
	public void go() {


		instanceStopped = false ;
		
		startEngines();
		
		PrintLog.Delay(2000) ;
		// we stop from the outside by writing a file "stop" to the config directory
		while ( instanceStopped == false){
			PrintLog.Delay(100) ;
		}
		astorInstance.close(0) ;

	}

	
	/**
	 * 
	 * @param somtype 0=default: simple, single run; 1=som optimizer
	 * @param lastProjectName2 
	 */
	private void startEngines(){
		
		if (astorInstance!=null){
			return;
		}

		out.print(1,"starting project <"+ IniProperties.lastProjectName+"> ...");
		
		// setting worktypes
		
		
		astorInstance = new AstorInstance( this );
		
		if (arguments!=null){
			astorInstance.contextMode = arguments.getContextMode() ;
			
			astorInstance.homedir      = (String)arguments.getMappedTopic("homeDir");
			astorInstance.projectname  = (String)arguments.getMappedTopic( new String[]{"project","prj","proj"});
			
			 
			 

			astorInstance.logLevel     = (Integer)arguments.getMappedTopic("loglevel");
			
			astorInstance.glueMode = SomFluidFactory._GLUE_MODULE_ENV_NONE ;
			
			astorInstance.resumeMode   = true;
			astorInstance.onCompletion = (String)arguments.getMappedTopic("oncompletion"); 
			
						  int nc = (Integer)arguments.getMappedTopic( new String[]{"nodecount","size"});
						  if (nc<=3){
							  nc=60;
						  }
			astorInstance.setNodeCount( nc ) ;
			 
			astorInstance.appSecret    = (String)arguments.getMappedTopic("appsecret");
			astorInstance.waitfor      = (Integer)arguments.getMappedTopic("waitFor"); 
			astorInstance.processName  = (String)arguments.getMappedTopic("name");
			
			astorInstance.setArguments( arguments.getArgumentsObj());
			// this needs a simple tcp box...
		}
		
		boolean hb = astorInstance.checkForConfiguration();
		
		if (hb==false){
			astorInstance.close(-5);
		}
						int oport = arguments.getOutPort();
						int iport = arguments.getInPort();

						
		astorInstance.prepareTcpBox(oport,iport);  // must be before the wait object !
		
		if ((astorInstance.contextMode.toLowerCase().contentEquals("itexx")) &&
			(astorInstance.waitfor>=1)){
			// waitfor-secret for testing is "adkhf-23487asdf-3487sdfr-324"
			out.print(2, "Application will wait a few seconds for final clearance...");
			astorInstance.waitfor();
		}
		
		
		// instance will check whether it could resume...
		astorInstance.startInstance() ;
		
	}

	
}




@SuppressWarnings("rawtypes")
/*
-homedir:"D:/data/iTexx/app/Astor" 
-cfg:itxapp-config.xml
-context:itexx
-comm: in-7205,out-7206
-name:itexxwin
-loglevel:2




 */
class Arguments extends ArgumentsCliReaderAbstract implements ArgumentsIntf {
	
	public final String _APP_COMPLETION_EXIT    = InstanceProcessControlIntf._APP_COMPLETION_EXIT ;
	public final String _APP_COMPLETION_SERVICE = InstanceProcessControlIntf._APP_COMPLETION_SERVICE ;
	
	public final String  _APP_CONTEXT_ITEXX = InstanceProcessControlIntf._APP_CONTEXT_ITEXX ;
	public final String  _APP_CONTEXT_ALONE = InstanceProcessControlIntf._APP_CONTEXT_ALONE ;
	

	String sourceFileDedicated="",sourceFilesByFolder="",sourceFileByListingFile="";
	
	protected ArgumentsPublicIntf arguments ;
	public Map argumentsMap;
	
	
	
	// ------------------------------------------------------------------------
	@SuppressWarnings("unchecked")
	public Arguments(){
		super();
		setParent( this ) ;
		
		//default = standalone
		contextMode = InstanceProcessControlIntf._APP_CONTEXT_ALONE ; // itexx or standalone, running user based projects	
	}
	// ------------------------------------------------------------------------

	// preparation of arguments and stable parts of the set of arguments 
	// is outsourced to the abstract class
	// else the basic parts of the check are presented in a more convenient way
	
	@SuppressWarnings("unchecked")
	@Override
	public ArgumentsPublicIntf parse( String[] _args ){
		
		String avStr, str;
		
		
		// jarDir = fileutil.getUserDir();
		str = fileutil.getUserHomeDir() ;
		str = IniProperties.fluidSomProjectBasePath; // before, we passed readbinpref() !
		homeDir = DFutils.createPath( str, "app/Astor/") ;
		
		
		defineArguments( new String[]{ "prj","homedir","cfg","sourcemode","size",
				                       "resume","onCompletion","name","comm",
				                       "startSomClients","context","waitfor",
				                       "loglevel"});
		
		try {
		
			arguments = prepareArguments( homeDir, _args ) ;

		} catch (Exception e) {
			showArguments( getDescription() );
			System.exit(0);			
		}  
		
		argumentsMap = getArgumentsMap();
		
		
		
		if (handlingTreatment( new String[]{"prj","proj","project"})){
		
			projectName = (String)getMappedTopic( new String[]{"prj","proj","project"} );
			
			
			AstorSomStartup.setLastProjectName(projectName);
			IniProperties.lastProjectName = projectName;
			
			str = IniProperties.getFluidSomProjectBasePath() ;
			if (IniProperties.getsBinPath().length()==0){
				
				str = (new PathFinder()).getAppBinPath(this.getClass(), false);
				IniProperties.setBinPath(str) ;
			}
			
			IniProperties.saveIniProperties();
			str = IniProperties.getFluidSomProjectBasePath() ;
		}
		
		int rn = remainingTopics.size();
		
		// the rest
		if (rn>0){
			for (int i=0;i<rn;i++){
				String topic = (String) remainingTopics.get(i); 
				avStr = getArgumentValueStr( new String[]{topic} );
				if (avStr.length()>0){
					
					if (topic.toLowerCase().contentEquals("startsomclients")){
						// -startSomClients:1,7211,7210
						String[] scs = avStr.split(",") ;
						if (scs.length==3){
							if (strgutil.isNumericX(scs[0])){
								startSomClients = strgutil.getNumFromStr(scs[0], 0);
							}
							int portnum = 1;
							if (strgutil.isNumericX(scs[1])){
								portnum = strgutil.getNumFromStr(scs[1], 0);
								if (portnum>1090){
									inPort = portnum;  
								}
							}  
							if (strgutil.isNumericX(scs[2])){
								portnum = strgutil.getNumFromStr(scs[2], 0);
								if (portnum>1090){
									outPort = portnum;
								}
								
							}
						}
					}
				}// sth found
			}//i->
		}
		
		if (_args.length==0){
			showArguments( getDescription() );
			System.exit(0);
		}
		
		if (defaultsRequested){
			
			homeDir     = fileutil.createpath( fileutil.getUserDir(), "Astor") ;
			projectName = "itexx" ;
			configFile  = fileutil.createpath( homeDir, "astor-config.xml") ;
			// this file will be read by DocoControlProperties.readSettings()
		}
		
				
				
		setReference( (Object)this);
		return (ArgumentsPublicIntf) this;
	}
	

	
	/*
		-prj:"test2"
		-homedir:"D:/data/iTexx/DocumentServer"
		-cfg:"D:/data/iTexx/DocumentServer/test1/config/docoserv-config.xml"
	 */

	
	

	public boolean startApplet() {
		return appletRequested;
	}

	
	@Override
	public String get_APP_COMPLETION_EXIT() {
		return _APP_COMPLETION_EXIT;
	}

	@Override
	public String get_APP_COMPLETION_SERVICE() {
		return _APP_COMPLETION_SERVICE;
	}

	@Override
	public String get_APP_CONTEXT_ITEXX() {
		return _APP_CONTEXT_ITEXX;
	}

	@Override
	public String get_APP_CONTEXT_ALONE() {
		return _APP_CONTEXT_ALONE;
	}

	public ArgumentsPublicIntf getArguments() {
		return arguments;
	}

	@Override
	public String[] getDescription() {
		String[] dParts = new String[3];
		 
		
		dParts[0] = "Values (examples) appear subsequent to the : \n"+
		        	"-prj:\"test2\"  \n"+
		        	"-homedir:\"D:/data/iTexx/app/Astor\" \n"+
		        	" \n" ;

		dParts[1] = "Default values are activated by parameter \"-default\" or \"-d\" and are set to: \n"+
			        "-prj: docoserv  \n"+
					"-homedir: <path of jar>/DocumentServer \n"+
					"\n";
		
		
		dParts[2] = "Additional Information: \n"+
		      "- The database file will be written to the folder \"<homedir>/<project name>/storage\".  \n"+
		      "- If no configuration file has been provided, a default file will be created into \n" +
		      "  the folder \"<homedir>/<project name>/config\". \n"+
		      "  Note that you then have to edit the configuration file, namely the section defining the \n"+
		      "  the folders to be observed.\n"+
		      "- You may stop the application by creating a file \"stop\" within the folder containing \n"+
		      "  the configuration file.  \n"+
		      "- The parameters for activating the notification are port numbers, (1) in, (2) out, where \n"+
		      "  the in-port allows for some udimaentary control, such like stopping the application, or \n"+
		      "  re-reading the configuration. \n"+
		      "- For starting the interactive applet version (e.g. for testing) use the \n"+
		      "  parameter \"-a\" or \"-applet\" \n\n"+" ";
		
		return dParts;
	}

	@Override
	public int[] getPorts() {
		return ports;
	}

	@Override
	public int[] getServicePorts() {		
		return servicePorts ;
	}

	@Override
	public String getAppSecret() {
		return appsecret;
	}

	
}


class AstorInstance extends AppInstanceAbstract{
  
	 
	
	
	SomFluidFactory sfFactory;
	SomFluidProperties sfProperties;
	SomFluidPropertiesHandlerIntf sfPropertiesDefaults;
	
	SomFluidProbTaskIntf sfTask;
	
	
	int instanceType;
	int nodeCount = 400;
	
	App app;
	
	// ========================================================================
	public AstorInstance(App app){
		
		// these two string values are just for convenience of console output, 
		// it is not used by the application itself for any control
		super( "AstorSomApp", "SomModuleInstance");
		
		processName = "astor";
		
		this.app = app;
		
		instance = this;
		out = app.out ;
	}
	
	
	// ========================================================================
	

	protected void setNodeCount(int nodecount) {
		
		if (nodecount>25){
			nodeCount = nodecount;
		}
	}


	protected void startInstance() {
		
		appSecret = app.arguments.getAppSecret() ;
		
		instanceType = FieldIntf._INSTANCE_TYPE_ASTOR ;
		instanceThrd.start();
	}
	
	protected void resume() {
		// 
		
		resumeMode = checkForPossibleResuming();
		instanceThrd.start();
	}


	private boolean checkForPossibleResuming() {
		
		return false;
	}
	
	protected boolean checkForConfiguration() {
		// 
		return true;
	}
	
	
	@Override // from abstract
	protected void resumeInstance() throws Exception{
		
		// loads an existing targeted SOM and starts/continues/repeats the optimizing according to the settings 
		// results are saved or provided to the Glue, then the Som-layer stops / application exits
	
	
		
		String startupTraceInfo="", lastproject="", systemroot="", propertiesFileName, dir;
		String[] infoStrings, infopart;
		FileOrganizer fileorg ;
		
		try {
											System.out.println("resuming...");
			instanceType = FieldIntf._INSTANCE_TYPE_SOM;
			
			startupTraceInfo = SomFluidFactory.loadStartupTrace( instanceType ) ;
		
			infoStrings = startupTraceInfo.split("\n");
			
			for (int i=0;i<infoStrings.length;i++){
				infopart = infoStrings[i].split("::");
				if (infopart[0].contains("cfgroot")) {
					systemroot = infopart[1];
				}
				if (infopart[0].contains("project")) {
					lastproject = infopart[1];
				}
			}
			
			if ((systemroot.length()==0) || (lastproject.length()==0) || (DFutils.fileExists(systemroot )==false)){
				out.printErr( 1, "Cannot resume, since boot/trace file was not found or it did not contain the relevant information.\n"+
							     "Astor will start normally, next time it will start in resume mode.\n") ;
				prepareInstance();
				return;
			}
			
			// load properties, still only as a bootstrap...
			sfProperties = SomFluidProperties.getInstance();
			sfProperties.setInstanceType( instanceType ) ;
			 
			fileorg = sfProperties.getFileOrganizer() ;
			
			sfProperties.setSystemRootDir(systemroot) ;
			sfProperties.getPersistenceSettings().setPathToSomFluidSystemRootDir(systemroot) ;
			sfProperties.getPersistenceSettings().setProjectName(lastproject) ;
			
			fileorg.setPropertiesBase(sfProperties);
			
			dir = "";
			dir = fileorg.getObjectStoreDir("");
			propertiesFileName = DFutils.createPath( dir, SomFluidProperties._STORAGE_OBJ ) ;
			
			// now loading the desired properties into a new object;
			ContainerStorageDevice storageDevice ;
			storageDevice = new ContainerStorageDevice();
			
			sfProperties = (SomFluidProperties)storageDevice.loadStoredObject(propertiesFileName) ;
			
			sfProperties.setFileOrganizer(fileorg) ;
			
			sfFactory = SomFluidFactory.get(sfProperties);	
			processControl = sfFactory.getSomProcessControl() ; // sending messages into the SomProcess, like interrupt, injecting new best metric, changing properties and threshold on the fly ...
											sfFactory.getOut().print(2, "loading description of previous task ...");
			// loading the task and starting it (file = SomFluidTask.trace)
			Object taskObj = sfFactory.loadTaskTrace(lastproject);
			
			if (taskObj==null){
				
				SomFluidMonoTaskIntf sfTask = (SomFluidMonoTaskIntf)sfFactory.createTask( ); 
				sfTask.setContinuity( 1,1) ;                 
				sfTask.setStartMode(1) ;
	
				sfTask = (SomFluidMonoTaskIntf)sfFactory.createTask( ); 
				sfTask.setStartMode(1) ;  
				sfTask.setContinuity(2,0,200);
				
				sfFactory.produce( sfTask );
			}else{
				if (taskObj instanceof SomFluidMonoTaskIntf) {
					SomFluidMonoTaskIntf sfTask = (SomFluidMonoTaskIntf)taskObj ;
					sfTask.setResumeMode(1);
											sfFactory.getOut().print(2, "putting previous task to the queue...");
					sfFactory.produce( sfTask );
				}
				if (taskObj instanceof SomFluidProbTaskIntf) {
					SomFluidProbTaskIntf sfTask = (SomFluidProbTaskIntf)taskObj ;
					sfTask.setResumeMode(1);
					sfFactory.produce( sfTask );
				}
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}




	protected void prepareInstance() {

			
		
		// this might be called with some URL or xml-string that represents the source containing the settings
		// if this exists, it will be loaded
		
		sfProperties = SomFluidProperties.getInstance( "" ); // not available
		
		defineDataBaseAccessData();
		
		// alternatively... load from /resources in jar ...
		 
		
		sfProperties.setApplicationContext(contextMode);
		
		sfPropertiesDefaults = new SomFluidPropertiesHandler(sfProperties);
		
		// dir = fileorg.getObjectStoreDir(pathitx)
		
		if (DFutils.folderExists(sfProperties.getSystemRootDir())==false){
			sfProperties.setSystemRootDir( IniProperties.fluidSomProjectBasePath );
		}

		SomFluidStartup.setLastProjectName(projectname); 
		SomFluidStartup.setProjectBasePath(homedir);
		AstorSomStartup.setLastProjectName(projectname); 
		AstorSomStartup.setProjectBasePath(homedir);

		sfProperties.getPersistenceSettings().setProjectName(projectname);
		sfProperties.getPersistenceSettings().setAppNameShortStr("astor");
		sfProperties.getPersistenceSettings().setPathToSomFluidSystemRootDir( sfProperties.getSystemRootDir() );
		sfProperties.getFileOrganizer().setRootDir( sfProperties.getSystemRootDir() );
		sfProperties.getFileOrganizer().setProjectDirName(DFutils.createPath(homedir, projectname)) ;
		sfProperties.getFileOrganizer().setProjectBaseDir(homedir);
		/*
		org.NooLab.somfluid.app.up.IniProperties = new IniProperties( IniProperties.fluidSomProjectBasePath,
				   													  IniProperties.lastProjectName,
				   													  IniProperties.dataSource);
											 // _projectBasePath,_lastProjectName, _dataSource
	    */
		
		explicitlySettingProperties();
		
		sfProperties.setStreamingActive(0);
		sfProperties.setAstorInitializationRecordCount(2000); // 3000
		sfProperties.setAstorInitializationDocCount(20) ;
		
		sfProperties.setOnCompletion( onCompletion );
		
		sfFactory = SomFluidFactory.get(sfProperties);					   // creating the factory; calling without "factorymode" parameter, optimizer will be assumed	
		 
		sfFactory.setTcpBox( getTcpBox() );
		
		sfFactory.saveStartupTrace( FieldIntf._INSTANCE_TYPE_SOM, 
									sfPropertiesDefaults.getStartupTraceInfo() );
		sfProperties.save();
		sfProperties.exportXml();  					// String xstr = sfProperties.getExportedXml();
		
		
		/*
		 * everything is started by "SomFluid" through a queued task mechanism;
		 * 
		 * different application types use different perspectives onto the task
		 * 
		 */
		
		
		
		sfTask = (SomFluidProbTaskIntf)sfFactory.createTask( FieldIntf._INSTANCE_TYPE_ASTOR ); //
		
		sfTask.setStartMode(1) ;             		// default=1 == starting after producing the FluidSom
										 			//        <1 == only preparing, incl. 1 elementary run to load the data, 
		                                 			//              but not starting the modeling process (v switches in the middle between 3..100)
										 			//        >100  minimum delay in millis
		
		
		sfTask = (SomFluidProbTaskIntf)sfFactory.createTask( ); 
		sfTask.setStartMode(1) ;  
		 
		 
		sfTask.activateDataStreamReceptor(true) ;   // after learning the initial bunch of data
													// Astor Som switches to "online learning"
		
		// these have been provided as :  -startSomClients:1,7211,7210
		
		// first we request an object
		
		SomTaskDependProcessIntf dependencies = sfFactory.getTaskDependenciesObject(); 
		
		dependencies.setDependencyType( ITexxPublicIntf._ITX_DEPENDENT_PROCESS_SOMCLIENTS) ;
		
		
					int oport = app.arguments.getOutPort();
					int iport = app.arguments.getInPort();
		
		dependencies.setCommPorts( iport,oport);// 7211,7210);
		
		sfTask.setDependencies(dependencies);

		
		String str = sfProperties.getApplicationContext() ;
		sfTask.setApplicationContext(str);
		
		
		
		try {
			
			sfFactory.produce( sfTask );
							// this produces the SomFluid and the requested som-type according to
							// SomFluidProperties._SOMTYPE_MONO, referring implicitly to sfTask; 
							
		} catch (Exception e) {
			e.printStackTrace();
		}          		
		

		
	 	// if we like to have graphical output, then start the applet for displaying it and 
		// define shake hands by means of GlueClients...
		
		str = str + " " ;
	}
 
	


	private void defineDataBaseAccessData() {

		DataBaseAccessDefinition dbAccess ;
		TexxDataBaseSettingsIntf dbSettings ;
		
		
		try {
			
			// reading from  dbDefinitionResource ="texx-db-definition-xml" ;
			sfProperties.getDatabaseDefinitionInfo("randomwords", TexxDataBaseSettingsIntf._DATABASE_STRUC_CONTEXTS_L0);
			 
			dbAccess = sfProperties.getDbAccessDefinition() ;
			 
			dbSettings = sfProperties.getDatabaseSettings() ;
			
			// ArrayList<String> fieldlist = dbSettings.getTableFields() ;
			
		} catch (Exception e) {
			
			e.printStackTrace();
		}
		
	}
	
	@SuppressWarnings("unused")
	private void explicitlySettingProperties(){
		
		 
		PersistenceSettings ps;
		 

		String str, dbDefinitionResource="" ;
		
		try {
			
			
			String instance = "astor";
			
			if (instance.contentEquals("astor")){

				sfPropertiesDefaults.setInstance( "astor" ,nodeCount );
				//check this !!
				instanceType = sfProperties.getSomInstanceType() ;
									
				sfProperties.setSomType( FieldIntf._SOMTYPE_PROB ) ; // == associative storage = Astor
				
				// choose a fixed or a fluid grid
				sfPropertiesDefaults.setGridType( FieldIntf._SOM_GRIDTYPE_FIXED ) ;
			    //sfPropertiesDefaults.setGridType( FieldIntf._SOM_GRIDTYPE_FLUID) ;
				
				
				// choose a guessing instance: low-resolution grid, speeding the 
				// node selection in large grids
				
				
				
				// this applies only if the instance is of type "som", which includes optimizing of the model
				// the absolute number of different models that will be checked
				sfPropertiesDefaults.setOptimizerStoppingCriteria( -1 ) ;					
									//	optionally, any of the following parameters ( [n], 21, 100, 0.8)


				/* we may create a complete som for classification from externally defined "top-down" profiles
				   that's very important in design approaches
				   note that the data file will be interpreted as a collection of prototypes;
				   yet, if the data contain more records than it has been defined as the number of prototypes,
				   it will be regarded as empirical data  	
				   by default = Off */
				sfPropertiesDefaults.setDataSimulationByPrototypes( 0 );				// or any number >100 for switching on
				sfPropertiesDefaults.setMaxNumberOfPrototypes(50) ;
				
				/*
				 * the "outcome" or target can be mapped onto a binary variable
				 * level of definition parameters may be "raw" or "relative" (=normalized, hence expressing percentage quantiles)
				 * 
				 * will be overridden by settings from the optional description file about variable settings
				 */
				// sfPropertiesDefaults.setSingleTargetDefinition( "raw", 0.1, 0.41, "intermediate" ) ;
									// the Single-Target-Mode can be defined with several non-contiguous intervals within [0..1] 
				
									// we have to check rather soon whether such values occur at all 
									// in the TV column of the table: on data import, or reloading of the SomData 
				
				sfPropertiesDefaults.activateGrowingOfSom( false, 300, 15.1) ; // n = max node size, averaged across the top 15% of nodes acc. to size

			}

			// variables...
			defineInitialVariableSettings(); 
									// alternatively, defineInitialVariableSettings([filename]);
									// (re-)creating the file
									// sfPropertiesDefaults.exportVariableSettings(null, ""); // a dedicated path could be applied
			 
			
			// -------------------------------------------------------------------------------
			
			// "file", "db", "tcp"
			sfPropertiesDefaults.setDataSourcing( DataStreamProviderIntf._DSP_SOURCED_DB ,0) ;
			// sfPropertiesDefaults.setDataSourcing( DataStreamProviderIntf._DSP_SOURCED_FILE ,0) ;
			
			sfPropertiesDefaults.setDataSourceName( IniProperties.dataSource );
			
			//
			// ... overruling by setting a database as source 
			sfPropertiesDefaults.setDataSourcing( DataStreamProviderIntf._DSP_SOURCED_DB ,0) ;
			// dbDefinitionResource = "texx-db-definition-xml" ; // default
			sfPropertiesDefaults.setDatabaseDefinitionResource( dbDefinitionResource,
																"randomwords", 
																TexxDataBaseSettingsIntf._DATABASE_STRUC_CONTEXTS_L0);
			
			
			 
			// -------------------------------------------------------------------------------
			// optional, if there are indeed plugin files ...
			// dependent on appcontext
			if (sfProperties.isITexxContext()){
				
											out.print(2, "context detected : itexx");				
				str = sfProperties.getSystemRootDir();
											out.print(4, "system root (1): "+str);				
				if (str.length()==0){
					
					sfProperties.setSystemRootDir( IniProperties.fluidSomProjectBasePath) ;
					str = sfProperties.getSystemRootDir();    // D:/data/iTexx/  ... it is empty when started by iTexx
											out.print(4, "system root (2): "+str);				
					if (str.length()==0){
						str = DFutils.getParentDir(homedir, 2);
						sfProperties.setSystemRootDir( str) ; // D:/data/iTexx/app/Astor
						str = sfProperties.getSystemRootDir();
											out.print(4, "system root (3): "+str);				
					}
											out.print(4, "system root (4): "+str);						
				}
				 
				
				str = DFutils.createPath( sfProperties.getSystemRootDir(), "app/Astor/plugins/") ;
out.print(4, "system root + partial algo path : "+str);				
				sfPropertiesDefaults.setAlgorithmsConfigPath( str );
			}else{
				sfPropertiesDefaults.setAlgorithmsConfigPath( "D:/dev/java/somfluid/plugins/" );
			}
			

			 
			
			sfProperties.addFilter( "var",0.3,"<",1,1,true);       
									// filter that act on the values of observations
			   						// can be defined only with an existing factory since we need access to the data
			   						// !! not yet functional

			str = IniProperties.fluidSomProjectBasePath;
			sfPropertiesDefaults.initializeDefaults();
			
			
			str = sfProperties.getSystemRootDir() ;
			str = IniProperties.fluidSomProjectBasePath;
			
			if (sfProperties.isITexxContext()==false){
				sfProperties.setSystemRootDir(str) ;
			}
			
			
			sfProperties.setExtendingDataSourceEnabled(true); 
			
			
			// controlling the granularity/verbosity of console messages 
			if (LogControl.Level>2){
				sfProperties.setShowSomProgress( SomFluidProperties._SOMDISPLAY_PROGRESS_STEPS ) ; // default: _SOMDISPLAY_PROGRESS_BASIC
			}
			sfProperties.setShowSomProgress( SomFluidProperties._SOMDISPLAY_PROGRESS_STEPS );
			
			sfProperties.setMultiProcessingLevel(0); 
			
		} catch (Exception e) {
			e.printStackTrace();
			System.err.println("The system will exit.");
			System.exit(-7) ;
		}
		
		// --- --- ---

		/*
		 * in this folder there will be enumerated sub-folders containing the results
		 */
		String resultFolder ;
		
		resultFolder = sfPropertiesDefaults.setResultsPersistence(1,"app/Astor");	// optionally: a dedicated path
		resultFolder = sfPropertiesDefaults.getResultBaseFolder();

		// set ready flag
		sfProperties.setInitializationOK(true) ;						
	}
	
	  
	 
	 
	// ----------------------------------------------------
	
	/**
	 * a small compartment, which optionally also may read the initial variable settings from a file
	 * 
	 * @param filename
	 * @throws Exception 
	 */
	private void defineInitialVariableSettings( String ...filenames) throws Exception {
	
		boolean configByFileExcluded=false;
		String[] filnames = new String[0];
		
		// TODO -> variables ... excludedFromNormalization as ArrayList<String>, incl wildcard
		//         into properties as suggestion, which will be expanded later upon import
		//         Variables.setVariableSettings(), explicateGenericVariableRequests() ;

		// from data description field in section [nonormalization] 
	
		if ((filenames!=null) && (filenames.length>0)){
			filnames = new String[ filenames.length];
			System.arraycopy(filenames, 0, filnames, 0, filnames.length) ;
		}
		
		if ((configByFileExcluded==false) && ((filenames==null) || (filenames.length==0) || (DFutils.fileExists(filenames[0])==false))){
			// String str  =IniProperties.lastProjectName; // = Astor
			
			String filepath = IniProperties.fluidSomProjectBasePath;
			
			if (contextMode.contentEquals(InstanceProcessControlIntf._APP_CONTEXT_ITEXX )){
				if (filepath.toLowerCase().contains("app/astor")==false){
					filepath = DFutils.createPath( filepath , "app/Astor");
				}
			}
			
			filepath = DFutils.createPath( filepath , IniProperties.lastProjectName);
			
			filepath = DFutils.createPath( filepath , "data/description/");
			filepath = DFutils.createPath( filepath , "astor-variables.txt");
			
			String filename = sfPropertiesDefaults.checkForVariableDescriptionFile(0, filepath) ; 
			// 0 = typology file, 1 = textual description (background information)
			
			if (DFutils.fileExists(filename)){
				filnames = new String[]{filename};
			}
		}
		
		if ((filnames!=null) && (filnames.length>0) && (DFutils.fileExists(filnames[0]))){
			 
			if (sfPropertiesDefaults.loadVariableSettingsFromFile( filnames[0]) ){
				// recognizes format by itself, if successful, we may return
				return;
			}
		}
		
		// .................. do the following only if there was not a definition file
		
		
		// note that the data are not loaded at that point,
		// such it is only a request for blacklisting variables
		// if any those variables do not exist, no error message will appear by default
		
		// we provide a small interface for dealing with initial variable settings all at once
		// VariableSettingsHandlerIntf variableSettings = sfPropertiesDefaults.getVariableSettingsHandler();
	
		// variableSettings.setTargetVariables(""); 	
		// variableSettings.setTvGroupLabels("") ;
	
		sfProperties.getModelingSettings().setTargetedModeling(false) ;
		sfProperties.getModelingSettings().setTvGroupLabels("");
		sfProperties.addFieldExclusionByIndex(15);
		sfProperties.setFieldExclusionByIndexFrom(15);
		sfProperties.setFieldExclusionByIndexUntil(15);
		sfProperties.setFieldExclusionByIndexFrom("wordlabel", 1); 
		sfProperties.setFieldExclusionByIndexUntil("wordlabel"); 
		sfProperties.setFieldExclusionByBetween(2,15);
	
	}



	
}



